import java.applet.*;
import java.awt.*;
import java.lang.*;

public class Particles extends Applet implements Runnable
{
 private double rl,rh,tx1,ty1,tx2,ty2;
 private double rmsvel,rad,cost,sint,vel2;
 private Color c,cbkg;
 private int num=20;
 boolean frozen=false;
 private Graphics g,offscreen;
 Image offImage;
 Thread animatorThread;
 double[] x=new double[num+1];
 double[] xx=new double[num+1];
 double[] y=new double[num+1];
 double[] yy=new double[num+1];
 double[] vel=new double[num+1];
 int[] cr=new int[num+1];
 int[] cg=new int[num+1];
 int[] cb=new int[num+1];

 public void init()
{
 rl=350;
 rh=327;
 for (int i=1;i<=num;i++)
{
 x[i]=(Math.random()*(rl-20)+10);
 xx[i]=(Math.random()*5);
 y[i]=(Math.random()*(rh-20)+10);
 yy[i]=(Math.random()*5);
 vel2=xx[i]*xx[i]+yy[i]*yy[i];
 vel[i]=Math.sqrt(vel2);        
 cr[i]=(int)Math.round(Math.random()*255);
 cg[i]=(int)Math.round(Math.random()*255);
 cb[i]=(int)Math.round(Math.random()*255);
}
 cbkg=Color.white;
// c=Color.blue; 
}
 
 public void start()
{
 if (!frozen)
{ 
 if (animatorThread == null) animatorThread = new Thread(this);
 animatorThread.start();
} 
}
 
 public void stop()
{
 animatorThread=null;
}
    
 public boolean mouseDown(Event e, double x, double y) 
{
  if (frozen) 
{
     frozen = false;
     start();
}
 else 
{
     frozen = true;
     stop();
}
 return true;
} 

 public void paint(Graphics g)
{
	update(g);
}

        public void update( Graphics g ) {
                Dimension d=size();
                if (offscreen == null) {
                      offImage=createImage(d.width,d.height);
                      offscreen=offImage.getGraphics();
                }
		 offscreen.setColor(cbkg);
		 offscreen.fillRect(0,0,(int)rl,(int)rh);
		 offscreen.setColor(Color.black);
		 offscreen.drawRect(0,0,(int)rl-1,(int)rh-1);
		 offscreen.drawRect(1,1,(int)rl-2,(int)rh-2);
		 for(int i=1;i<=num;i++)
		{
		 offscreen.setColor(new Color(cr[i],cg[i],cb[i]));
		 offscreen.fillOval((int)x[i],(int)y[i],10,10);
		 offscreen.setColor(Color.red);
		 offscreen.drawRect(0,0,50,(int)(rmsvel*15));
		 offscreen.setColor(Color.black);
		 offscreen.drawRect(0,0,50,(int)(vel[i]*15));
		}
                g.drawImage(offImage,0,0,this);
        }
 
 public void run()
{
  while (Thread.currentThread()==animatorThread)
{
  paint(this.getGraphics());
  for (int i=1;i<=num;i++)
{ 
  for (int k=1;k<=num;k++)
    if(k!=i)
{
  rad= Math.sqrt((x[i]-x[k])*(x[i]-x[k]) + (y[i]-y[k])*(y[i]-y[k]));
  if (rad<=10)
{
     tx1=xx[k];ty1=yy[k];tx2=xx[i];ty2=yy[i];
     cost=(x[k]-x[i])/rad;
     sint=(y[k]-y[i])/rad;
     xx[k]=(tx2*cost-ty1*sint);
     xx[i]=(tx1*cost-ty2*sint);
     yy[k]=(tx2*sint + ty1*cost);
     yy[i]=(tx1*sint + ty2*cost);      
}

}
  if ( x[i]<=(rl-10) && x[i] >=10) x[i]+=xx[i];
  else 
{ 
   if(x[i]<10)xx[i]=Math.abs(xx[i]);
   if(x[i]>rl-10)xx[i]=-Math.abs(xx[i]);
    x[i]+=2*xx[i];
}  
  if ( y[i]<(rh-10) && y[i] >10) y[i]+=yy[i];
  else 
{ 
   if(y[i]<10)yy[i]=Math.abs(yy[i]);
   if(y[i]>rh-10)yy[i]=-Math.abs(yy[i]);
    y[i]+=2*yy[i];
}  
}
  rmsvel=0.0;
  for (int k=1;k<=num;k++)
{
    vel2=xx[k]*xx[k]+yy[k]*yy[k];
    vel[k]=Math.sqrt(vel2);        
    rmsvel=rmsvel+vel2;
}
  rmsvel=Math.sqrt(rmsvel/num);
  showStatus("rms velocity="+rmsvel+"pix/r");
  for (int j=1;j<100000;j++);
}
}

} 
